package monfox.stack.iec61850.mms.client.impl;

import java.util.List;
import java.util.Vector;

import monfox.log.Logger;
import monfox.stack.iec61850.api.ModelCommunicationException;
import monfox.stack.iec61850.api.ModelServiceException;
import monfox.stack.iec61850.api.ModelTimeoutException;
import monfox.stack.iec61850.api.ModelValueException;
import monfox.stack.iec61850.api.ObjectReference;
import monfox.stack.osi.mms.MMS;
import monfox.stack.osi.mms.MMSAPI;
import monfox.stack.osi.mms.ObjectName;

public abstract class ACSI_Service {
    private MmsIEC61850ClientApi a = null;
    private MmsIEC61850Client b = null;
    private String c = null;
    private boolean d = false;

    private int e = 30000;
    private int f = 0;
    private boolean g = false;

    private boolean h = false;
    private boolean i = false;
    private boolean j = false;
    private List k = new Vector();

    private Result l = null;

    private static Logger m = Logger.getInstance("DOSI", "IEC61850-SERVICES", "ACSI_Service");

    ACSI_Service(MmsIEC61850Client paramMmsIEC61850Client, String paramString) {
        this.b = paramMmsIEC61850Client;
        this.a = paramMmsIEC61850Client.a();

        this.c = paramString;
    }

    public MmsClientModelApi getModelApi() {
        return (MmsClientModelApi) this.b.getModelApi();
    }

    public MmsIEC61850Client getClient() {
        return this.b;
    }

    public MmsIEC61850ClientApi getClientApi() {
        return this.b.a();
    }

    public MMS getValidMMS() throws ModelCommunicationException {
        return this.b.getValidMMS();
    }

    private synchronized boolean f() throws ModelTimeoutException {
        return !g();
    }

    private synchronized boolean g() throws ModelTimeoutException {
        m.detailed("invoking done()");
        if (this.f >= this.k.size()) {
            if (this.h) {
                m.detailed("done() -- completed, rv = true;");
                return true;
            }

            m.detailed("done() -- waiting");
            a(this.e);
            return g();
        }

        m.detailed("done() -- rv=false");
        return false;
    }

    private synchronized void a(long paramLong) throws ModelTimeoutException {
        if (m.isDetailedEnabled()) {
            m.detailed("* waiting for confirmation");
        }

        try {
            if (paramLong > 0L) {
                long l1 = System.currentTimeMillis();
                long l2;
                long l3 = l2 = paramLong;// * 1000L;
                while (true) {
                    if (m.isDetailedEnabled()) {
                        m.detailed("-- waiting for " + paramLong + " seconds");
                    }

                    super.wait(l3);

                    if (m.isDetailedEnabled()) {
                        m.detailed("-- wait(" + l3 + ") returned ...");
                    }

                    if ((this.h) || (this.f < this.k.size()))
                        break;
                    long l4;
                    long l5;
                    if ((l5 = (l4 = System.currentTimeMillis()) - l1) >= l2) {
                        throw new ModelTimeoutException("timeout waiting for response");
                    }

                    l3 = l2 - l5;
                }

            } else {
                while ((!this.h) && (this.f >= this.k.size())) {
                    m.detailed("-- waiting unlimited");
                    super.wait();
                    m.detailed("-- wait() returned");
                }
            }
        } catch (InterruptedException localInterruptedException) {
            m.debug("interrupted exception ", localInterruptedException);
        }

        m.detailed("-- awakened");

        m.detailed("-- confirmation received");
    }

    final synchronized Result d() throws ModelServiceException, ModelCommunicationException, ModelValueException {
        e();
        Result localResult;
        if (this.l != null) {
            localResult = this.l;
        } else {
            if (!isRunInBackground()) {
                j();
            }
            localResult = h();
        }

        if (localResult == null)
            return null;

        if (localResult.getException() != null) {
            throw localResult.getException();
        }

        return localResult;
    }

    private synchronized Result h() throws ModelTimeoutException {
        m.detailed("nextResult()");

        if (f()) {
            Result localResult = (Result) this.k.get(this.f++);

            if (m.isDetailedEnabled()) {
                m.detailed(" response = " + localResult);
            }
            this.l = localResult;
            return localResult;
        }

        return null;
    }

    final synchronized void a(Result paramResult) {
        this.k.add(paramResult);
        this.h = true;

        i();
    }

    private synchronized void i() {
        m.detailed("notifyResult");
        try {
            c();

            m.detailed("-- invoking confirmation listener");
        } catch (Exception localException) {
            m.error("error in handle response", localException);
        } catch (Throwable localThrowable) {
            m.error("ready listener exception", localThrowable);
        }

        m.detailed("-- notifying all");
        super.notifyAll();
    }

    abstract void c();

    public void isRunInBackground(boolean paramBoolean) {
        this.d = paramBoolean;
    }

    public boolean isRunInBackground() {
        return this.d;
    }

    final synchronized ACSI_Service e() throws ModelCommunicationException, ModelServiceException, ModelValueException {
        if (isStarted())
            return this;

        int i1 = 1;
        Object localObject = this;
        this.j = true;
        a();

        if (isRunInBackground()) {
            // localObject = new a(0);
            getClient().a((Runnable) localObject);
        }

        return (ACSI_Service) this;
    }

    private synchronized void j() {
        if (isFinished())
            return;
        Object localObject;
        try {
            try {
                b();
            } catch (ModelServiceException localModelServiceException) {
                localObject = a(localModelServiceException);
//				a((Result) localObject);
            } catch (Exception localResult) {
                localObject = new ModelServiceException("error in processing service '" + getServiceName() + "'",
                        localResult);

//				m.error("ACSI_Service error", (Throwable) localObject);
//				m.error("ACSI_Service error", localResult);
//				Result local = a((ModelServiceException) localObject);
//				a(local);
            }
        } catch (Exception e) {
            System.err.println("cccccccccccccc");
            e.printStackTrace();
        }
        int i1 = 1;
        ACSI_Service localACSI_Service = this;
        this.i = true;
    }

    public boolean isFinished() {
        return this.i;
    }

    public boolean isStarted() {
        return this.j;
    }

    abstract Result a(ModelServiceException paramModelServiceException);

    public String getServiceName() {
        return this.c;
    }

    public int getTimeoutMillis() {
        return this.e;
    }

    public void setTimeoutMillis(int paramInt) {
        this.e = paramInt;
    }

    final ObjectName a(String paramString) {
        ObjectReference param = new ObjectReference(paramString);

        switch (param.getScope().ordinal()) {
            case 1:
                return ObjectName
                        .Domain(this.a.getMMSAPI(), param.getLDName(), getClient().convert2mms(param.getDataRef()));
            case 2:
                return ObjectName.AA(this.a.getMMSAPI(), getClient().convert2mms(param.getDataRef()));
            case 3:
                return ObjectName.Vmd(this.a.getMMSAPI(), getClient().convert2mms(param.getDataRef()));
        }

        return ObjectName.Domain(this.a.getMMSAPI(), this.b.getDefaultLDeviceName(),
                getClient().convert2mms(param.getDataRef()));
    }

    public MMSAPI getMMSAPI() {
        return this.a.getMMSAPI();
    }

    abstract void a() throws ModelCommunicationException, ModelValueException;

    abstract void b() throws ModelCommunicationException, ModelValueException, ModelTimeoutException;

    class a implements Runnable {
        private a() {
        }

        public final void run() {
            try {
                ACSI_Service.this.a();
            } catch (ModelCommunicationException e) {
                e.printStackTrace();
            } catch (ModelValueException e) {
                e.printStackTrace();
            }
        }
    }

    public class Result {
        private ModelServiceException a;

        Result() {
        }

        Result(ModelServiceException arg2) {
            this.a = arg2;
        }

        public ModelServiceException getException() {
            return this.a;
        }
    }
}